# -*- coding: utf-8 -*-
#############################
####### client module #######
#############################
########## INFO #############
#
# program: chat
#    file: guiclient.py
#  python: version 2.6 is required
#     use: python guiclient.py
#   autor: Andrey Goncharov
# version: 0.9.9 RC2
#  update: 5.4.2011
#
from Tkinter import *
from tkFileDialog import *
import fileinput
import tkMessageBox
from sys import *
from time import *
import client
from threading import *
import threading
import os.path
from cPickle import loads

try:
    root = Tk()
    class Get_msg(Thread):
        def __init__(self):
            Thread.__init__(self)
        # background job
        def run(self):
             Tag_name=StringVar()
             Tag_start=StringVar()
             Tag_end=StringVar()
             Name_length=StringVar()
             count=0
             while 1:
                  if client.status[-1] == "DISCONNECTED":
                      RESO_VAR.set("")
                      Tex1.delete("1.0",END)
                      NICKS_TEXT.delete("1.0",END)
                      #STATUS.config(bg="#aaaaaa")
                      status_frame.config(bg="#333333")
                      count=0
                      sleep(1)
                      if client.status[-1] == "CONNECTED":
                          count=0
                          Tex1.delete("1.0",END)
                          #STATUS.config(bg="#5da130")
                          status_frame.config(bg="#5da130")
                  if len(client.data)>0:
                       count+=1
                       MSG_that_received=client.data.pop(0)
                       Splitted_msg=MSG_that_received.split(":")
                       #beta tagz-----------------------------
                       if len(Splitted_msg)==2:
                           Name_length.set(str(int(len(Splitted_msg[0]))+1))
                           Tag_name.set("name"+str(count))
                           Tag_start.set(str(count)+"."+"0")
                           Tag_end.set(str(count)+"."+Name_length.get())
                           Tex1.insert(END,MSG_that_received+"\n")
                           Tex1.yview_pickplace("end")
                           Tex1.tag_add(Tag_name.get(),
                                        Tag_start.get(),
                                        Tag_end.get())
                           Tex1.tag_config(Tag_name.get(),
                                           foreground="#5da130",
                                           font=("fixedsys",11,"underline"))
                       else:
                           Tex1.insert(END,MSG_that_received+"\n")
                           Tex1.yview_pickplace("end")
                       #end of beta tagzz---------------------
                  if len(client.online)>0:
                        online=[]
                        online.extend(client.online)
                        client.online=[]
                        NICKS_TEXT.delete("1.0",END)
                        NICKS_TEXT.insert("1.0","Users online:\n")
                        while len(online)>0:
                            NICKS_TEXT.insert(END,online.pop(0)+"\n")
                  if len(client.topic)>0:
                      RESO_VAR.set(client.topic.pop())
   
    GO=Get_msg()
    GO.setDaemon(True)
   
    class Connector(Thread):
        def __init__(self):
            Thread.__init__(self)
        def run(self):
            while 1:
                if client.status[-1] == "DISCONNECTED":
                    client.connect()
   
    connector=Connector()
    connector.setDaemon(True)
   
    class Work(Thread):
        def __init__(self):
            Thread.__init__(self)
        def run(self):
            while 1:
                if RESO_VAR.get() == "DISCONNECTED":
                    sleep(5)
                    client.connect()
   
    #Checking whether the DefaultConf.txt exists or not
    def Check_for_defaults():
        if os.path.exists("DefaultConf.txt")==True:
            CONFS=open("DefaultConf.txt","r")
            IP_VARIABLE.set(CONFS.readline().strip())
            PORT_VARIABLE.set(CONFS.readline().strip())
            NICK_VARIABLE.set(CONFS.readline().strip())
            CONFS.close()
        else:
            IP_VARIABLE.set("109.171.79.111")
            PORT_VARIABLE.set("6001")
   
    #Loading configs from the file
    def _open():
        op = askopenfilename()
        if op:
            F=open(op,"r")
            IP_VARIABLE.set(F.readline().strip())
            PORT_VARIABLE.set(F.readline().strip())
            NICK_VARIABLE.set(F.readline().strip())
            F.close()
        else:
            pass
       
    #Saving configs to the file    
    def _save():
        sa=asksaveasfilename()
        if sa:
            f = open(sa,"w")
            f.write(IP_ENTRY.get().strip()+"\n"+
                    PORT_ENTRY.get().strip()+"\n"+
                    NICK_ENTRY.get().strip())
            f.close()
        else:
            pass
   
    #Proceed to the chatroom with your custom configs saved
    def proceed_to_chat():
         IP_VALUE=IP_ENTRY.get().strip()
         PORT_VALUE=PORT_ENTRY.get().strip()
         NICK_VALUE=NICK_ENTRY.get().strip()
         TT = open("DefaultConf.txt","w")
         TT.write(IP_VALUE.strip()+"\n"+
                  PORT_VALUE.strip()+"\n"+
                  NICK_VALUE.strip())
         TT.close()  
         Tex1["state"]="normal"
         Tex2["state"]="normal"
         client.host=IP_VALUE
         client.port=int(PORT_VALUE)
         client.nicks.append(NICK_VALUE)
         win.destroy()
         GO.start()
         connector.start()
   
    #Check whether the nick is valid and then
    def check_nick():
        if len(NICK_ENTRY.get().strip())==0:
            tkMessageBox.showwarning("Alarm", "Your nick shall not be so short.")
            NICK_VARIABLE.set("")
        elif NICK_ENTRY.get().count("#")>0:
            tkMessageBox.showwarning("Alarm", "Baad symbol in your nick (\#)")
            NICK_VARIABLE.set("")
        elif NICK_ENTRY.get().count(":")>0:
            tkMessageBox.showwarning("Alarm", "Baad symbol in your nick (:)")
            NICK_VARIABLE.set("")
        elif NICK_ENTRY.get().count("\\n")>0:
            tkMessageBox.showwarning("Alarm", "Baad symbol in your nick (\\n)")
            NICK_VARIABLE.set("")
        elif NICK_ENTRY.get().count("\\t")>0:
            tkMessageBox.showwarning("Alarm", "Baad symbol in your nick (\\t)")
            NICK_VARIABLE.set("")
        else:
            Proceed_to_chat=proceed_to_chat()
   
    #root exit menu command
    def Exit():
        root.destroy()
        client.disconnect()
        sys.exit(0)
         
    #Return Send
    def Send(Event):
        if Event.keysym=="Return":
            MSG_to_send=Tex2.get('1.0',END+"-1c").strip()
            Tex1.yview_pickplace("end")
            client.send(MSG_to_send)
            Tex2.delete("1.0",END)
        else:
            pass
   
    #Win.defaults button
    def Set_defaults():
        IP_VARIABLE.set("109.171.79.111")
        PORT_VARIABLE.set("6001")
   
    #Options window
    def Options_are_created():

        #set theme
        def Set_theme(Event):
            if Theme_box.get(ACTIVE)=='Default':
                root.config(bg="#bbbbbb")
                Tex1.config(bg="#fffacd",fg="#000000",
                            width=48,height=20,font=('times',11),
                            insertbackground="#fffacd")
                Tex2.config(bg="#cadaba",fg="#000000",
                            width=48,height=3,font=('times',11),
                            insertbackground="#000000")
                frame1.config(width=446,height=271)
                frame2.config(width=446,height=70)  
   
            if Theme_box.get(ACTIVE)=='Blue':
                root.config(bg="#1a4780")
                Tex1.config(bg="#4682b4",fg="#505050",
                            font=("comic sans ms",11),
                            insertbackground="#4682b4")
                Tex2.config(bg="#6495ed",fg="#505050",
                            width=38,height=3,
                            font=("comic sans ms",11),
                            insertbackground="#505050")
   
            if Theme_box.get(ACTIVE)=='Matrix':
                root.config(bg="#bbbbbb")
                Tex1.config(bg="#000000",fg="#00ff00",
                            font=("fixedsys",11),
                            insertbackground="#000000")
                Tex2.config(bg="#000000",fg="#00ff00",
                            insertbackground="#00ff00",
                            font=("fixedsys",11))
                frame1.config(bg="#78866b")
                frame2.config(bg="#78866b")
   
        Opt_win=Toplevel(root)
        Opt_win.title("Options")
        Opt_win.geometry("250x190+700+400")
   
        Choose_theme=Label(Opt_win,text="Choose theme")
       
        Themes = ['Default','Blue','Matrix']
        Theme_box = Listbox(Opt_win,selectmode=SINGLE,height=4)
        for i in Themes:
            Theme_box.insert(END,i)
        Theme_box.bind("<Double-Button-1>",Set_theme)
   
        Choose_theme.place(relx=0.5,rely=0.25,anchor=CENTER)
        Theme_box.place(relx=0.5,rely=0.5,anchor=CENTER)
   
    def Get_size(Event):
        root.update()
        RESO_VAR.set(root.winfo_geometry())
        RESO_VAR.set(client.servers)

    #custom root size for you reso
    def Set_size_on_start():
        width_root=StringVar()
        height_root=StringVar()
        X_co=IntVar()
        Y_co=IntVar()
        height_root.set(int(root.winfo_screenheight())*5/9)
        width_root.set(int(height_root.get())*13/16)
        X_co.set((int(root.winfo_screenwidth())-int(width_root.get()))/2)
        Y_co.set((int(root.winfo_screenheight())-int(height_root.get()))/2)
        root.geometry(width_root.get()+"x"+
                      height_root.get()+"+"+
                      str(X_co.get())+"+"+
                      str(Y_co.get()))

    #Tex1 popup menu
    def PopUpTex1(event):
        try:
            Tex1Pop.post(event.x_root, event.y_root)
        finally:
            Tex1Pop.grab_release()

    #Tex2 popup menu
    def PopUpTex2(event):
        try:
            Tex2Pop.post(event.x_root, event.y_root)
        finally:
            Tex2Pop.grab_release()

    #Text formating
    def copy(wi):
        try:
            wi.clipboard_clear()
            text = wi.get("sel.first", "sel.last")
            wi.clipboard_append(text)
        except:
            pass
    
    def cut(wi):
        try:
            copy(wi)
            wi.delete("sel.first", "sel.last")
        except:
            pass

    def paste(wi):
        try:
            text = wi.selection_get(selection='CLIPBOARD')
            wi.insert('insert', text)
        except:
            pass


    #Size and position of the root window    
    Set_sizza=Set_size_on_start()
    root.config(bg="#bbbbbb")
    root.title("Failover chat")
    root.minsize(width=320,height=426)
   
    #Set variables for the win.entry() widgets
    IP_VARIABLE=StringVar()
    PORT_VARIABLE=StringVar()
    NICK_VARIABLE=StringVar()
   
    """Toplevel window which provides us with such awesome features as
    IP, Nick and port setting"""
   
    #Size and position of the TopLevel window
    win = Toplevel(root,bd=10,bg="#bbbbbb")
    win.title("Log in")
    win.geometry("250x150+200+400")
    win.minsize(width=210,height=150)
   
   
    #Win Menu
    WinMenu=Menu(win,bg="#bbbbbb")
    win.config(menu=WinMenu,bg="#bbbbbb")
    FileMenu = Menu(WinMenu,bg="#bbbbbb",tearoff=0,activebackground="#999999")
    WinMenu.add_cascade(label="File",menu=FileMenu)
    FileMenu.add_command(label="Save configs...",command=_save)
    FileMenu.add_command(label="Load configs...",command=_open)
    FileMenu.add_command(label="Exit",command=Exit)
   
   
    #Wins Widgets initialising
    CONNECT_BUTTON=Button(win, text="Connect", command=check_nick,
                          bg="#aaaaaa",overrelief=GROOVE)
    DEFAULT_BUTTON=Button(win, text="Default", command=Set_defaults,
                          bg="#aaaaaa",overrelief=GROOVE)
   
    IP_LAB=Label(win,text="IP/HOST:",bg="#bbbbbb")
    IP_ENTRY=Entry(win,width=15,textvariable=IP_VARIABLE,
                   bg="#000000",fg="#00ff00",
                   insertbackground="#00ff00")
   
    PORT_LAB=Label(win,text="PORT:",bg="#bbbbbb")
    PORT_ENTRY=Entry(win,width=15,textvariable=PORT_VARIABLE,
                     bg="#000000",fg="#00ff00",
                     insertbackground="#00ff00")
   
    NICK_LAB=Label(win,text="NICK:",bg="#bbbbbb")
    NICK_ENTRY=Entry(win,width=15,textvariable=NICK_VARIABLE,
                     bg="#000000",fg="#00ff00",
                     insertbackground="#00ff00")
   
   
    DEFAULT_IP_LAB=Label(win,text="Default IP is 109.171.79.111",bg="#bbbbbb")
    DEFAULT_PORT_LAB=Label(win,text="Default Port is 6001",bg="#bbbbbb")
   
    #Setting widgets' positions
    IP_LAB.grid(row=0,column=0,sticky=W)
    IP_ENTRY.grid(row=0,column=1,padx=1)
    PORT_LAB.grid(row=1,column=0,sticky=W)
    PORT_ENTRY.grid(row=1,column=1,padx=1)
    NICK_LAB.grid(row=2,column=0,sticky=W)
    NICK_ENTRY.grid(row=2,column=1,padx=1)
    DEFAULT_IP_LAB.grid(row=3,column=0,columnspan=2,sticky=W)
    DEFAULT_PORT_LAB.grid(row=4,column=0,columnspan=2,sticky=W)
    CONNECT_BUTTON.grid(row=5,column=0,sticky=E,padx=20)
    DEFAULT_BUTTON.grid(row=5,column=1,sticky=W,padx=20)
         
    CHECK1488=Check_for_defaults()        
   
    """Root window with an unbelievable functions"""
   
   
    #First frame with the incoming messages
    frame1=Frame(root)

    #status frame
    status_frame=Frame(root,width=10,height=10,bg="red")

    #test label
    RESO_VAR=StringVar()
    RESO=Label(root,textvariable=RESO_VAR,bg="#bbbbbb",font=("courer",11,'bold'))
    RESO.bind("<Button-3>",Get_size)

    #inner frames
    frame_filler=Frame(frame1,bg="#bbbbbb",width=13)
    frame_nicks=Frame(frame1,bg="#000000",width=90)

    #list of the online users
    NICKS_TEXT=Text(frame_nicks,width=12,
                    font=("times",11),bg="#000000",
                    fg="#00ff00")


    #incoming Text()
    Tex1=Text(frame1,
              wrap=WORD,
              bg="#000000",
              fg="#00ff00",
              font=("fixedsys",11),
              insertbackground="#000000",
              relief=SUNKEN,
              state=DISABLED)
   
    #incoming Scrollbar
    sbar1 = Scrollbar(frame1)
   
    #Setting sbar1 as Tex1 scroll
    sbar1.config(command=Tex1.yview)
    Tex1.config(yscrollcommand=sbar1.set)
    Tex1.bind("<Button-3>",PopUpTex1)

    Tex1Pop = Menu(Tex1, tearoff=0)
    Tex1Pop.add_command(label="Copy",command=lambda:copy(Tex1))

    #Second frame with users TextArea
    frame2=Frame(root)          
   
    #User's Text()
    Tex2=Text(frame2,
              wrap=WORD,
              bg="#000000",
              fg="#00ff00",
              font=("fixedsys",11),
              insertbackground="#00ff00",
              relief=SUNKEN,
              state=DISABLED)

    #User's scrollbar
    sbar2 = Scrollbar(frame2)
   
    #Setting sbar2 as user's scroll
    sbar2.config(command=Tex2.yview)
    Tex2.config(yscrollcommand=sbar2.set)
    
    Tex2Pop = Menu(Tex2, tearoff=0)
    Tex2Pop.add_command(label="Copy",command=lambda:copy(Tex2))
    Tex2Pop.add_command(label="Paste",command=lambda:paste(Tex2))
    Tex2Pop.add_command(label="Cut",command=lambda:cut(Tex2))
    
    #binding sending messg after Enter in Tex2
    Tex2.bind("<KeyRelease>",Send)
    Tex2.bind("<Button-3>",PopUpTex2)
   
    #Root menu
    RootMenu=Menu(root,bg="#aaaaaa")
    root.config(menu=RootMenu)
    fm = Menu(RootMenu,tearoff=0,bg="#bbbbbb",activebackground="#999999")
    RootMenu.add_cascade(label="File",menu=fm)
    fm.add_command(label="Options",command=Options_are_created)
    fm.add_command(label="Exit",command=Exit)
   
    #root widgets positions

    status_frame.place(x=20,rely=0.025,anchor=CENTER)
    
    
    RESO.place(relx=0.5,rely=0.025,anchor=CENTER)
   
    frame1.place(relx=0.5,
                 rely=0.425,
                 relwidth=1,
                 y=7,
                 width=-14,
                 relheight=0.78,
                 anchor=CENTER)
   
    frame_nicks.pack(side=RIGHT,fill=Y)
    NICKS_TEXT.pack(fill=Y,expand=1)
    frame_filler.pack(side=RIGHT,fill=Y)
    sbar1.pack(side=RIGHT, fill=Y)
    Tex1.pack(side=LEFT, fill=BOTH,expand=1)
   
   
    frame2.place(relx=0.5,
                 rely=0.9,
                 relwidth=1,
                 y=7,
                 width=-14,
                 relheight=0.145,
                 anchor=CENTER)
   
    sbar2.pack(side=RIGHT, fill=Y)    
    Tex2.pack(side=LEFT, fill=BOTH,expand=1)
   
    root.mainloop()
except:
    print "Good bye"
#EOF

